﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Threading;
using Microsoft.Win32;
using System.Reflection;
using System.Diagnostics;
using System.IO;

namespace XbdSoft.ActiveX
{

    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    [ProgId("XbdSoft.ActiveX.DownloadActiveX")]
    [ClassInterface(ClassInterfaceType.AutoDual), ComSourceInterfaces(typeof(ControlEvents))] //Implementing interface that will be visible from JS
    [Guid("ECE236A9-AF9C-45DA-8D58-081907287FFE")]
    [ComVisible(true)]
    public class DownloadActiveX //: IObjectSafety
    {
        private string myParam = "Empty";

        public DownloadActiveX()
        {

        }

        public event ControlEventHandler OnClose;
         
        #region Download
        [ComVisible(true)]
        public void Download(long id)
        {
            try
            {
                var xbdSoftExePath = GetXbdSoftExePath();
                var fileName = Path.GetFileNameWithoutExtension(xbdSoftExePath);

                var processes = Process.GetProcessesByName(fileName);
                if (processes.Length > 0)
                {
                    var hWnd = processes[0].MainWindowHandle;
                    SendMessage(hWnd, DOWNLOADMSG, 0, (UInt32)id);

                    if (hWnd != GetForegroundWindow()) //获取当前活动窗体
                        SetForegroundWindow(hWnd); //如果不是,强制把自己的设置为活动窗体

                }
                else
                {
                    if (string.IsNullOrEmpty(xbdSoftExePath))
                    {
                        MessageBox.Show("您的机器上面还没有安装小布叮软件！");
                        Process.Start("iexplore.exe", "http://www.xbd61.com");
                        return;
                    }
                    else
                    {
                        ProcessStartInfo startInfo = new ProcessStartInfo(xbdSoftExePath, id.ToString());
                        Process.Start(startInfo);
                        // run the process.
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        #endregion

        #region  Helper
        private string GetXbdSoftExePath()
        {
            var registerPath = @"HKEY_LOCAL_MACHINE\SOFTWARE\XbdSoft";
            return Registry.GetValue(registerPath, "EXE", string.Empty).ToString();
        }

        #endregion

        #region Register Class

        ///	<summary>
        ///	Register the class as a	control	and	set	it's CodeBase entry
        ///	</summary>
        ///	<param name="key">The registry key of the control</param>
        [ComRegisterFunction()]
        public static void RegisterClass(string key)
        {
            // Strip off HKEY_CLASSES_ROOT\ from the passed key as I don't need it
            StringBuilder sb = new StringBuilder(key);

            sb.Replace(@"HKEY_CLASSES_ROOT\", "");
            // Open the CLSID\{guid} key for write access
            RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);

            // And create	the	'Control' key -	this allows	it to show up in
            // the ActiveX control container
            RegistryKey ctrl = k.CreateSubKey("Control");
            ctrl.Close();

            // Next create the CodeBase entry	- needed if	not	string named and GACced.
            RegistryKey inprocServer32 = k.OpenSubKey("InprocServer32", true);
            inprocServer32.SetValue("CodeBase", Assembly.GetExecutingAssembly().CodeBase);
            inprocServer32.Close();
            // Finally close the main	key
            k.Close();
            MessageBox.Show("Registered");
        }

        ///	<summary>
        ///	Called to unregister the control
        ///	</summary>
        ///	<param name="key">Tke registry key</param>
        [ComUnregisterFunction()]
        public static void UnregisterClass(string key)
        {
            StringBuilder sb = new StringBuilder(key);
            sb.Replace(@"HKEY_CLASSES_ROOT\", "");

            // Open	HKCR\CLSID\{guid} for write	access
            RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);

            // Delete the 'Control'	key, but don't throw an	exception if it	does not exist
            k.DeleteSubKey("Control", false);

            // Next	open up	InprocServer32
            //RegistryKey	inprocServer32 = 
            k.OpenSubKey("InprocServer32", true);

            // And delete the CodeBase key,	again not throwing if missing
            k.DeleteSubKey("CodeBase", false);

            // Finally close the main key
            k.Close();
            MessageBox.Show("UnRegistered");
        }
        #endregion

        #region Send Message

        protected const UInt32 USER = 0x400;
        protected const UInt32 DOWNLOADMSG = USER + 1;
        protected const UInt32 WM_COPYDATA = 0x004A;

        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage(
        IntPtr hWnd,        // 信息发住的窗口的句柄
        UInt32 Msg,            // 消息ID
        UInt32 wParam,         // 参数1
        UInt32 lParam // 参数2   [MarshalAs(UnmanagedType.LPTStr)]StringBuilder lParam
        );
         [StructLayout(LayoutKind.Sequential)]
        public struct SENDDATASTRUCT
        { 
            public UInt32 dwData;

             public UInt32 cbData; 
             [MarshalAs(UnmanagedType.LPStr)]
             public string lpData;
        }

        #endregion

        #region Set Window to Top

         [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, ExactSpelling = true)]
         public static extern IntPtr GetForegroundWindow();  //获得当前活动窗体的句柄
         [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
         public static extern bool SetForegroundWindow(IntPtr hWnd);

        #endregion

         //#region Implement IObjectSafety
         //public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
         //{
         //    pdwSupportedOptions = 1;
         //    pdwEnabledOptions = 2;
         //    return 0;
         //}

         //public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
         //{
         //    return 0;
         //}
         //#endregion
    }

    /// <summary>
    /// Event handler for events that will be visible from JavaScript
    /// </summary>
    public delegate void ControlEventHandler(string redirectUrl);


    /// <summary>
    /// This interface shows events to javascript
    /// </summary>
    [Guid("AAA73195-F5F0-4375-9C0E-2FB165FD8B3F")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface ControlEvents
    {
        //Add a DispIdAttribute to any members in the source interface to specify the COM DispId.
        [DispId(0x60020001)]
        void OnClose(string redirectUrl); //This method will be visible from JS
    }
}
